﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;

namespace WeForms
{
    public class TouchContainerControl : UserControl
    {
        public static readonly List<Type> SuspendedControls;

        static TouchContainerControl()
        {
            SuspendedControls = new List<Type>
                                    {
                                        typeof (TextBoxBase),
                                        typeof (ScrollableControl),
                                        typeof (ScrollBar),
                                        typeof (ListView),
                                        typeof (ListControl),
                                        typeof (ListBox),
                                        typeof (TrackBar)
                                    };
        }
        public int TouchScrollSensitivity { get; set; }

        private Point _start = new Point(0, 0);
        private Point _mouse = new Point(0, 0);


        private MouseState _mouseState;

        private enum MouseState
        {
            Normal = 0,
            Down = 1,
            Moving = 2,
        }

        public TouchContainerControl()
        {
            TouchScrollSensitivity = 5;
        }

        protected override void OnMouseDown(MouseEventArgs e)
        {
            base.OnMouseDown(e);

            if (e.Button != MouseButtons.Left) return;

            if (!IsDraggable(e.Location))
            {
                return;
            }

            // store mouse position
            _mouse = new Point(e.X, e.Y);
            _start = AutoScrollPosition;
            _mouseState = MouseState.Down;
        }

        protected virtual bool IsDraggable(Point point)
        {
            // Always allow dragging
            Control control = GetChildAtPoint(point);
            if (control != null)
            {
                foreach (Type type in SuspendedControls)
                {
                    if (control.GetType().IsAssignableFrom(type))
                    {
                        return false;
                    }
                }
            }

            return true;
        }

        protected override void OnMouseUp(MouseEventArgs e)
        {
            base.OnMouseUp(e);
            // stop dragging
            _mouseState = MouseState.Normal;
        }


        protected override void OnMouseMove(MouseEventArgs e)
        {
            base.OnMouseMove(e);
            if (_mouseState == MouseState.Normal)
            {
                return;
            }

            // calculate how far we moved
            Point newPosition = new Point(e.X, e.Y);
            Point offset = new Point((_mouse.X - newPosition.X), (_mouse.Y - newPosition.Y));


            if (_mouseState == MouseState.Down)
            {
                // check if we moved the min-difference
                if (Math.Abs(offset.X) >= TouchScrollSensitivity ||
                    Math.Abs(offset.Y) >= TouchScrollSensitivity)
                {
                    _mouseState = MouseState.Moving;
                    OnStartTouchScrolling(e);
                }
            }

            // and update offset
            if (_mouseState == MouseState.Moving)
                AutoScrollPosition = new Point(-_start.X + offset.X,
                                               -_start.Y + offset.Y);
        }


        protected virtual void OnStartTouchScrolling(MouseEventArgs e)
        {

        }
    }
}
